//
//  ViewController.swift
//  CoreDataForPOCT
//
//  Created by Ryan Chen on 20/03/2018.
//  Copyright © 2018 Ryan Chen. All rights reserved.
//

import Cocoa
import CoreData

class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {

    @IBOutlet weak var tableView: NSTableView!
    @IBOutlet weak var beginDate: NSDatePicker!
    @IBOutlet weak var endDate: NSDatePicker!
    @IBOutlet weak var checkDate: NSDatePicker!
    var fetchedResultsController : NSFetchedResultsController<Menstrual>!
    
    var context : NSManagedObjectContext!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        
        guard let app = NSApp.delegate as? AppDelegate else {
            return
        }
        
        var calendar = Calendar.current
//        calendar.locale = Locale.current
//        calendar.timeZone = TimeZone.current
        
        Swift.print("locale\(calendar.locale) timezone: \(calendar.timeZone)")
        
        beginDate.dateValue = Date()
        endDate.dateValue = Date()
        checkDate.dateValue = Date()
        
        context = app.persistentContainer.viewContext
//        fetchController =
        
        let req = NSFetchRequest<Menstrual>(entityName: Menstrual.entity().name!)
        req.sortDescriptors = [NSSortDescriptor(key: "begin", ascending: true)]
        fetchedResultsController = NSFetchedResultsController<Menstrual>(fetchRequest: req, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
        fetchedResultsController.delegate = self
        
//        arrayController.bind(.contentArray, to: fetchedResultsController, withKeyPath: "fetchedObjects", options: nil)
        
        try! fetchedResultsController.performFetch()
        
        tableView.dataSource = self
        tableView.delegate = self
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }

    @IBAction func addMenstrual(_ sender: Any) {
        
        let r = NSEntityDescription.insertNewObject(forEntityName: Menstrual.entity().name!, into: context) as! Menstrual
        var calendar = Calendar.current
        r.begin = calendar.startOfDay(for: beginDate.dateValue)
        r.end = calendar.startOfDay(for: endDate.dateValue) + DateRange.secs

        r.type = 1

        try? context.save()
    }
    
    @IBAction func reloadButton(_ sender: Any) {
//        let r = DateRange(begin: Calendar.current.startOfDay(for: beginDate.dateValue),
//                          end: Calendar.current.startOfDay(for: endDate.dateValue),
//                          calendar: nil)
//        Swift.print("two date is \(r.count)")
//
//        let tmp = r.relation(to: checkDate.dateValue)
//        switch (tmp.0) {
//        case .after:
//            Swift.print("After \(tmp.1)")
//
//        case .inside:
//            Swift.print("Inside")
//
//        case .before:
//            Swift.print("Before \(tmp.1)")
//        }
//
        beginDate.dateValue = Date()
        endDate.dateValue = Date()
        tableView.reloadData()
    }
    
    private var menstrualInMonth = [DateRange]()
    
    @IBAction func searchButton(_ sender: Any) {

        guard let d = Calendar.current.range(of: .day, in: .month, for: checkDate.dateValue) else {
            Swift.print("get month range error")
            return
        }
        
        menstrualInMonth.removeAll()
        
        // get month 0 ~ end
        var c = Calendar.current.dateComponents([.year, .month], from: checkDate.dateValue)
        c.day = 0
        let begin = Calendar.current.date(from: c)
        c.day = d.count
        let end = Calendar.current.date(from: c)
        
        // search inside the month
        let req = NSFetchRequest<Menstrual>(entityName: Menstrual.entity().name!)
        req.sortDescriptors = [NSSortDescriptor(key: "begin", ascending: true)]
        req.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [NSPredicate(format: "begin <= %@", argumentArray: [end]), NSPredicate(format: "end >= %@", argumentArray: [begin])])
//        Swift.print("predicate string \(req.predicate?.predicateFormat)")
        
        let df = DateFormatter()
        df.dateFormat = "yyyy-MM-dd"
        do {
            if let records = try context.fetch(req) as? [Menstrual] {
//                Swift.print("get records \(records.count)")
                for r in records {
//                    Swift.print("search records end = \(df.string(from:r.end!))")
                    let dr = DateRange(begin: r.begin!, end: r.end!, calendar: nil)
                    Swift.print("duration: \(dr.count) begin: \(df.string(from:r.begin!)) end: \(df.string(from:r.end!))")
                    menstrualInMonth.append(dr)
                }
                
            }
        } catch (let e) {
            Swift.print(e)
        }
    }
    
    @IBAction func delButton(_ sender: Any) {
        Swift.print(#function)
        guard tableView.selectedRow >= 0 else {
            Swift.print("unselect now")
            return
        }
        
        let idx = IndexPath(item: tableView.selectedRow, section: 0)
        
        let o = fetchedResultsController.object(at: idx)
        
        context.delete(o)
        tableView.reloadData()
    }
    
    @IBAction func checkButton(_ sender: Any) {
//        guard let o = fetchedResultsController.fetchedObjects as? [Menstrual] else {
//            return
//        }
        let d = Calendar.current.startOfDay(for: checkDate.dateValue)
//        let d = checkDate.dateValue
        let df = DateFormatter()
        df.dateFormat = "yyyy-MM-dd HH:mm:ss"
        var flag = false
        for i in menstrualInMonth {
            let relation = i.relation(to: d)
            
            if relation.0 == .inside {
                i.dump()
                flag = true
                break
            }
        }
        
        if false == flag {
            Swift.print("no found in range")
        }
    }
    
    func numberOfRows(in tableView: NSTableView) -> Int {
        guard let o = fetchedResultsController.fetchedObjects as? [Menstrual] else {
            Swift.print("return no value")
            return 0
        }
        return o.count
    }

    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
//        Swift.print("tableColumn: \(tableColumn?.identifier.rawValue) row=\(row)")
        guard let col = tableColumn else {
            return nil
        }
        let df = DateFormatter()
        df.dateFormat = "yyyy-MM-dd HH:mm:ss"
        let idx = IndexPath(item: row, section:0)
        var v : NSTableCellView? = nil
        switch (col.identifier.rawValue) {
        case "begin":
            
            if let i = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier("beginView"), owner: self) as? NSTableCellView {
                i.textField?.stringValue = df.string(from: fetchedResultsController.object(at: idx).begin!)
                v = i
            }
            break

        case "end":
            if let i = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier("endView"), owner: self) as? NSTableCellView {
                i.textField?.stringValue = df.string(from: fetchedResultsController.fetchedObjects![row].end!)
                v = i
            }
            break

        case "type":
            if let i = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier("typeView"), owner: self) as? NSTableCellView {
                i.textField?.intValue = Int32(fetchedResultsController.fetchedObjects![row].type)
                v = i
            }
            break

        default:
            v = nil
        }

        return v
    }
}

extension ViewController : NSFetchedResultsControllerDelegate {
    func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
//        Swift.print("#function \(fetchedResultsController.fetchedObjects?.count)")

    }
    
    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
//        Swift.print("added a new row")
        tableView.reloadData()
    }
    
    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
        switch (type) {
        case .delete:
            Swift.print("delete")

        case .insert:
            Swift.print("insert")
            
        case .move:
            Swift.print("move")
            
        case .update:
            Swift.print("update")
        }
    }
}


